import { BehaviorSubject, Subscription, filter } from 'rxjs';
import { warn } from 'cc';

/**
 * 自放行循环
 * 
 * 
 * 
 *  Best Practice:
 * 
    
    let list = ['a', 'b', 'c', 'd'];
    const rscl = new RxSelfClearanceArrayLoop().init(list.length);
    if (rscl != null) { // length为0则为空，因此还是要判断
        this._sub = rscl.subscribe({
            next: _ => {
                let { v, self } = _;
                let item = list[v];
                // item is 'a', 'b', ...
            },
            complete: () => {
                this.log('@all complete');
            }
        })
        rscl.next();
    }

 */
export class RxSelfClearanceArrayLoop {

    static Create(totalCount: number) {
        return new RxSelfClearanceArrayLoop().init(totalCount);
    }

    _subject: BehaviorSubject<{ v: number, self: RxSelfClearanceArrayLoop }> = null;

    _totalCount: number = null;

    init(totalCount): RxSelfClearanceArrayLoop {

        if (totalCount == 0) {
            warn('RxSelfClearanceLoop 输入列表至少需要一个元素');
            return;
        }

        this._totalCount = totalCount;

        this._subject = new BehaviorSubject<{ v: number, self: RxSelfClearanceArrayLoop }>({ v: -1, self: this });
        return this;
    }

    subscribe(param: { next: (_: { v: number, self: RxSelfClearanceArrayLoop }) => void, complete?: () => void }): Subscription {
        return this._subject.pipe(filter(_ => _.v >= 0)).subscribe({ next: param.next, complete: param.complete });
    }

    next() {
        let curValue = this._subject.value.v;
        let nextValue = curValue + 1;
        if (nextValue == this._totalCount) {
            this._subject.complete();
        } else {
            this._subject.next({ v: nextValue, self: this });
        }
    }

    error(err) {
        this._subject.error(err);
    }
}